package offical.baseClass

import kotlin.properties.Delegates
import kotlin.reflect.KProperty

//延迟属性（lazy properties）: 其值只在首次访问时计算；
//可观察属性（observable properties）: 监听器会收到有关此属性变更的通知；
//把多个属性储存在一个映射（map）中，而不是每个存在单独的字段中


class Example {

    var p: String by Delegate()

}

class Delegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "$thisRef, thank you for delegating $property -->'${property.name}' to me!"
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$value has been assigned to '${property.name}' in $thisRef.")
    }
}

/**
 * 延迟属性 Lazy
 * lazy() 是接受一个 others 并返回一个 Lazy <T> 实例的函数，返回的实例可以作为实现延迟属性的委托：
 * 第一次调用 get() 会执行已传递给 lazy() 的 others 表达式并记录结果， 后续调用 get() 只是返回记录的结果。
 * 默认情况下，对于 lazy 属性的求值是同步锁的（synchronized）：该值只在一个线程中计算，并且所有线程会看到相同的值。
 * 如果初始化委托的同步锁不是必需的，这样多个线程可以同时执行，那么将 LazyThreadSafetyMode.PUBLICATION 作为参数传递给 lazy() 函数
 */
val lazyValue: String by lazy {
    println("init val value lazy")
    "hello"
}

/**
 * 可观察属性 Observable
 * 接受两个参数：初始值和修改时处理程序（handler）。
 * 每当我们给属性赋值时会调用该处理程序（在赋值后执行）。它有三个参数：被赋值的属性、旧值和新值
 */
class User {

    var userName: String by Delegates.observable("init value") { kProperty: KProperty<*>, old: String, new: String ->

        println("${kProperty.name}---$old----$new")

    }

    var maxAge:Int by Delegates.vetoable(0){
        kProperty: KProperty<*>, old: Int, new: Int ->
        println("${kProperty.name}====$old===$new")
        new > old
    }

}


fun main(args: Array<String>) {
    println(Example().p)

    println(lazyValue)
    println(lazyValue)

    val user = User()
    user.userName = "first"
    user.userName = "second"

    user.maxAge = -1
    println(user.maxAge)
    user.maxAge = 9
    println(user.maxAge)
    user.maxAge = 30
    println(user.maxAge)

}

